package com.xinzhidi.auth.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import com.xinzhidi.auth.service.SysLoginService;
import com.xinzhidi.common.core.domain.R;
import com.xinzhidi.common.core.exception.ServiceException;
import com.xinzhidi.common.core.utils.JwtUtils;
import com.xinzhidi.common.core.utils.StringUtils;
import com.xinzhidi.common.redis.service.RedisService;
import com.xinzhidi.common.security.auth.AuthLogic;
import com.xinzhidi.common.security.auth.AuthUtil;
import com.xinzhidi.common.security.service.TokenService;
import com.xinzhidi.common.security.utils.SecurityUtils;
import com.xinzhidi.system.api.model.LoginBody;
import com.xinzhidi.system.api.model.LoginUser;
import com.xinzhidi.system.api.model.OpenIdLoginBody;
import io.netty.handler.codec.DecoderException;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.mp.api.WxMpService;
import org.apache.commons.codec.binary.Hex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Map;

/**
 * token 控制
 *
 * @author xinzhidi
 */
@Slf4j
@RestController
public class TokenController {
    @Autowired
    private TokenService tokenService;

    @Autowired
    private SysLoginService sysLoginService;

    @Autowired
    private RedisService redisService;

//    @Autowired
//    private WxMaConfiguration wxMaConfiguration;

    @Autowired
    private WxMpService wxMpService;

    @Autowired
    private WxMaService wxMaService;

    @Value("${backUrl:}")
    private String backUrl;

    /** ,
     *
     * 前端用户轮询获取扫码是否扫码
     *
     * @param scene
     * @return
     */
    @RequestMapping("/getLoginStatus")
    public R getLoginStatus(@RequestParam String scene) {
        Map<String, Object> map = redisService.getCacheMap(scene);
        if (Boolean.FALSE.equals(redisService.hasKey(scene))) {
            return R.ok("等待用户扫码");
        }
//        if (map.get("status").equals(-1)) {
//            return R.fail("登录失败");
//        }
       redisService.deleteObject(scene);
        return R.ok(map);
    }

    /**
     * openId登录
     * 前端根据openId登录
     * @param form
     * @return
     */
    @PostMapping("openIdLogin")
    public R<?> openIdLogin(@RequestBody OpenIdLoginBody form) {
        // 用户登录
        LoginUser userInfo = sysLoginService.openIdLogin(form);

        // 获取登录token
        return R.ok(tokenService.createToken(userInfo));
    }

    /**
     * saomaLogin
     * 公众号扫码登录()
     * @param req
     * @param resp
     * @return
     */
    @GetMapping("saomaLogin")
    public void saomaLogin(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // 用户登录
        R<?> r;
        try {
            //菜单按钮的回调code 用于获取用户的openid
            String code = req.getParameter("code");
            String state = req.getParameter("state");
            log.info("接收到微信请求code：{}，state：{}",code,state);

            //获取openid
            String openid = "";

            WxOAuth2AccessToken accessToken = this.wxMpService.getOAuth2Service().getAccessToken(code);
            WxOAuth2UserInfo user = this.wxMpService.getOAuth2Service().getUserInfo(accessToken, null);
            openid = user.getOpenid();

            log.info("接收到微信用户user：{}",user.toString());

            if (StringUtils.isEmpty(openid)){
                r = R.fail("未找到用户");
            }else{
                OpenIdLoginBody form = new OpenIdLoginBody();
                form.setOpenId(openid);
                LoginUser userInfo = sysLoginService.openIdLogin(form);
                Map<String, Object> token = tokenService.createToken(userInfo);
                redisService.setCacheMap(state,token,60L);
                // 获取登录token
                r =  R.okMsg("登陆成功");
            }
        } catch (Exception e) {
            e.printStackTrace();
            String msg = e.getMessage().replaceAll("[^\u4e00-\u9fa5]", "");
            r = R.fail();
            if (StringUtils.isNotEmpty(msg)){
                r = R.fail(msg);
            }
        }
        log.info("接收到微信用户r.getMsg()：{},r.getCode()：{}",r.getMsg(),r.getCode());
        if (StringUtils.isEmpty(r.getMsg())){
            r.setMsg("操作成功");
        }
        resp.sendRedirect(backUrl+"/bweb/phoneMessageless.html?code="+r.getCode()+"&msg="+ URLEncoder.encode(r.getMsg()));
    }
    /**
     * PC端-小程序扫码登陆
     *
     * @param req
     * @return
     */
    @GetMapping("saomaMaLogin")
    public R<?> saomaMaLogin(HttpServletRequest req) throws IOException {
        // 用户登录
        R<?> r;
        //菜单按钮的回调code 用于获取用户的openid
        String scene = req.getParameter("scene");
        log.info("接收到微信请求scene：{}",scene);

        //微信openid/手机号登录
        LoginUser userInfo = sysLoginService.openIdLoginOrPhone(req);
        //获取token
        Map<String, Object> token = tokenService.createToken(userInfo);
        redisService.setCacheMap(scene,token,60L);
        // 获取登录token
        r =  R.okMsg("登陆成功");
        log.info("接收到微信用户r.getMsg()：{},r.getCode()：{}",r.getMsg(),r.getCode());
        if (StringUtils.isEmpty(r.getMsg())){
            r.setMsg("操作成功");
        }
        return r;
    }
    /**
     * 小程序登陆
     * @param req
     * @return
     */
    @GetMapping("maLogin")
    public R<?> maLogin(HttpServletRequest req) throws IOException {
        // 用户登录
        R<?> r;
        //微信openid/手机号登录
        LoginUser userInfo = sysLoginService.openIdLoginOrPhone(req);

        Map<String, Object> token = tokenService.createToken(userInfo);

        log.info("调试2微信小程序登录用户的角色：{}",userInfo.getRoles().toString());

        if (AuthLogic.hasRole(userInfo.getRoles(),"system") || AuthLogic.hasRole(userInfo.getRoles(),"admin")){
            return R.fail(500, "管理员不能登录小程序");
        }
        // 获取登录token
        r =  R.ok(token);
        log.info("接收到微信用户r.getMsg()：{},r.getCode()：{}",r.getMsg(),r.getCode());
        if (StringUtils.isEmpty(r.getMsg())){
            r.setMsg("操作成功");
        }
        return r;
    }

    /**
     * 手机号登录
     *
     * @param form
     * @return
     */
    @PostMapping("login")
    public R<?> login(@RequestBody LoginBody form) {

        // 用户登录
        LoginUser userInfo = sysLoginService.login(form);

        //除超管->其他人全部扫码登录
//        if (!userInfo.getSysUser().getUserType().equals(2)){
//            return R.fail("请扫码登录");
//        }

        // 获取登录token
        return R.ok(tokenService.createToken(userInfo));
    }

    @DeleteMapping("logout")
    public R<?> logout(HttpServletRequest request)
    {
        String token = SecurityUtils.getToken(request);
        if (StringUtils.isNotEmpty(token))
        {
            String username = JwtUtils.getUserName(token);
            // 删除用户缓存记录
            AuthUtil.logoutByToken(token);
            // 记录用户退出日志
            sysLoginService.logout(username);
        }
        return R.ok();
    }

    @GetMapping("test")
    public void test(HttpServletRequest request){
        throw new ServiceException("1111",111);
    }

    /**
     * 将16进制字符串转换为byte数组
     *
     * @param hexItr 16进制字符串
     * @return
     */
    public static byte[] hexItr2Arr(String hexItr) throws DecoderException {
        try {
            return Hex.decodeHex(hexItr);
        } catch (org.apache.commons.codec.DecoderException e) {
            e.printStackTrace();
        }
        return null;
    }

}
